﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NRemedy.MVC.UI
{
    public class JsonBuilder
    {
        public IDictionary<string, object> Properties
        {
            get;
            protected set;
        }

        public IDictionary<string,List<JsonBuilder>> Childrens
        {
            get;
            protected set;
        }

        public List<JsonBuilder> Collections
        {
            get;
            protected set;
        }

        private JsonBuilderRoot rootType; 

        public JsonBuilder() : this(JsonBuilderRoot.Object)
        {
        }

        public JsonBuilder(JsonBuilderRoot root)
        {
            rootType = root;
            if (rootType == JsonBuilderRoot.Collection)
                Collections = new List<JsonBuilder>();
            else
            {
                Properties = new SortedDictionary<string, object>();
                Childrens = new SortedDictionary<string, List<JsonBuilder>>();
            }
        }

        public void MergeProperty(string name, object value)
        {
            Properties[name] = value;
        }

        public void MergeChildObject(string name, JsonBuilder childObject)
        {
            if(!Childrens.ContainsKey(name)){
                Childrens.Add(name, new List<JsonBuilder>());
            }

            Childrens[name].Add(childObject);
        }

        public void MergeCollectionObject(JsonBuilder child)
        {
            Collections.Add(child);
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            if (rootType == JsonBuilderRoot.Object)
            {

                sb.Append("{");

                if (Properties.Count > 0)
                {
                    foreach (var p in Properties)
                    {
                        if (p.Value == null)
                        {
                            sb.Append("\"");
                            sb.Append(p.Key);
                            sb.Append("\":");
                            sb.Append("null");
                        }
                        else if (p.Value is Boolean)
                        {
                            sb.Append("\"");
                            sb.Append(p.Key);
                            sb.Append("\":");
                            sb.Append(p.Value.ToString().ToLower());
                        }
                        else if (p.Value is ValueType && !(p.Value is DateTime))
                        {
                            sb.Append("\"");
                            sb.Append(p.Key);
                            sb.Append("\":");
                            sb.Append(p.Value.ToString());
                        }
                        else
                        {
                            sb.Append("\"");
                            sb.Append(p.Key);
                            sb.Append("\":\"");
                            sb.Append(p.Value.ToString().ToSafeJsonString());
                            sb.Append("\"");
                        }

                        sb.Append(",");

                    }
                }


                if (Childrens.Count > 0)
                {
                    foreach (var child in Childrens)
                    {
                        sb.Append("\"");
                        sb.Append(child.Key);
                        sb.Append("\":[");
                        int count = child.Value.Count;
                        foreach (var j in child.Value)
                        {
                            count--;
                            sb.Append(j.ToString());
                            if (count != 0)
                                sb.Append(",");//trim end ,
                        }
                        sb.Append("],");
                    }

                }

                //trim end ,
                string ret = sb.ToString().TrimEnd(',');

                return ret + "}";

            }
            else
            {
                sb.Append("[");
                if (Collections != null && Collections.Count > 0)
                {
                    foreach (var c in Collections)
                    {
                        sb.Append(c.ToString());
                        sb.Append(",");
                    }
                }

                string ret = sb.ToString().TrimEnd(',');

                return ret + "]";
            }
        }
    }


    public enum JsonBuilderRoot
    {
        Object,
        Collection
    }
}
